
#include "GeosphereFace.h"

/*--------------------------------------------------------------------*/
GeosphereFace::GeosphereFace() {
	isDivided = false;
}

/*--------------------------------------------------------------------*/
void GeosphereFace::setVerts(vec3f a, vec3f b, vec3f c) {
	verts = new GeosphereVert*[3];
	verts[0] = new GeosphereVert();
	verts[1] = new GeosphereVert();
	verts[2] = new GeosphereVert();
	
	verts[0]->vert = a;
	verts[1]->vert = b;
	verts[2]->vert = c;

	calcFaceNorm();
}

/*--------------------------------------------------------------------*/
void GeosphereFace::calcFaceNorm() {

	faceNorm = cProd( 
		subVec(verts[2]->vert, verts[0]->vert),
		subVec(verts[1]->vert, verts[0]->vert)
	);

	faceNorm = normalize(faceNorm);

	// Keep all normals facing outward
	if ( dProd(verts[0]->unit, faceNorm) < 0 ) { 
		faceNorm = scaleVec(faceNorm,-1);
	}
}

/*--------------------------------------------------------------------*/
void GeosphereFace::doSplit(float r, int levelsLeft) {

	if ( --levelsLeft < 0 ) { return; }

	isDivided = true;

	vec3f ab = addVec(verts[0]->vert, verts[1]->vert);
	vec3f bc = addVec(verts[1]->vert, verts[2]->vert);
	vec3f ca = addVec(verts[2]->vert, verts[0]->vert);

	ab = scaleVec( normalize(ab), r );
	bc = scaleVec( normalize(bc), r );
	ca = scaleVec( normalize(ca), r );

	faces = new GeosphereFace[4];
	faces[0].setVerts( verts[0]->vert, ab, ca );
	faces[1].setVerts( verts[1]->vert, bc, ab );
	faces[2].setVerts( verts[2]->vert, ca, bc );
	faces[3].setVerts( ab, bc, ca );

	for ( int i = 0 ; i < 4 ; i++ ) { faces[i].doSplit(r, levelsLeft); }
}

/*--------------------------------------------------------------------*/
void GeosphereFace::collectFaces(list<GeosphereFace*>& faceList) {
	if ( !isDivided ) { return; }
	for ( int i = 0 ; i < 4 ; i++ ) {
		faceList.push_back(&faces[i]);
		faces[i].collectFaces(faceList);
	}
}

/*--------------------------------------------------------------------*/
GeosphereVert** GeosphereFace::getVerts() { return verts; }
bool GeosphereFace::getIsDivided() { return isDivided; }
const vec3f* GeosphereFace::getFaceNorm() { return &faceNorm; }
GeosphereFace* GeosphereFace::getFace(int i) { return &faces[i]; }
const GeosphereVert* GeosphereFace::getVert(int i) { return verts[i]; }
